# coding=utf-8
import arcpy
import os
import sys

# 设置默认编码为UTF-8
try:
    reload(sys)
    sys.setdefaultencoding('utf-8')
except NameError:
    pass

# 配置参数（已更新为用户提供的路径和要素类）
gdb_path = r"D:\ArcGis\DATA\DataExtraction.gdb"  # 数据库路径
feature_class = "SSPT_JW"  # 矢量数据名称

# 字段名称配置（已更新为用户提供的字段）
ADD_DATA_FIELD = "ADD_DATA"  # 用于标记数据状态的字段
CHECK_FIELDS = ["JH", "JHBM", "JLX"]  # 需要同时匹配的三个字段
OBJECTID_FIELD = "OBJECTID"  # 唯一标识字段


def safe_print(s):
    """安全打印包含中文的字符串，避免编码错误"""
    try:
        print(s)
    except UnicodeEncodeError:
        if isinstance(s, unicode):
            print(s.encode('gbk', errors='ignore'))
        else:
            print(str(s).decode('utf-8', errors='ignore').encode('gbk', errors='ignore'))


def check_fields_exist(fc_path):
    """检查必要字段是否存在及详细信息"""
    try:
        fields = arcpy.ListFields(fc_path)
        field_dict = {f.name: f for f in fields}  # 存储完整字段对象
        field_names = [f.name for f in fields]

        # 检查必要字段
        required_fields = [ADD_DATA_FIELD, OBJECTID_FIELD] + CHECK_FIELDS
        missing_fields = [f for f in required_fields if f not in field_names]
        if missing_fields:
            safe_print(u"错误：缺少必要字段：%s" % ", ".join(missing_fields))
            return None

        # 打印字段详细信息（用于调试）
        safe_print(u"\n===== 字段详细信息 =====")
        for field in required_fields:
            f = field_dict[field]
            safe_print(u"%s: 类型=%s, 长度=%d, 是否可为空=%s" %
                       (field, f.type, f.length, "是" if f.isNullable else "否"))

        # 检查比对字段类型（字符串类型更适合匹配）
        for field in CHECK_FIELDS:
            if field_dict[field].type != "String":
                safe_print(u"警告：%s字段类型不是String（实际为%s），可能影响匹配精度" %
                           (field, field_dict[field].type))

        return field_dict  # 返回完整字段对象字典

    except Exception as e:
        safe_print(u"字段检查失败：%s" % str(e))
        return None


def get_field_value_safely(value, field_type):
    """安全获取字段值，处理不同类型和编码问题"""
    try:
        if value is None:
            return "__NULL__", "空值"

        # 根据字段类型处理
        if field_type == "String":
            if isinstance(value, unicode):
                str_val = value.strip()
                return str_val, "Unicode字符串"
            else:
                str_val = str(value).strip().decode('utf-8', errors='replace')
                return str_val, "转换后的字符串"

        elif field_type in ["Integer", "SmallInteger", "Double", "Single"]:
            return str(value), "数值型"

        else:
            return str(value), "其他类型(%s)" % field_type

    except Exception as e:
        return "__ERROR__", "读取错误：%s" % str(e)


def get_old_data_combined_info(fc_path, field_dict):
    """获取旧数据的字段组合，增强字段读取调试"""
    combined_info = {}
    add_data_field = field_dict[ADD_DATA_FIELD]

    try:
        # 构建旧数据查询条件
        add_data_delimited = arcpy.AddFieldDelimiters(fc_path, ADD_DATA_FIELD)
        if add_data_field.type in ['Integer', 'SmallInteger']:
            where_clause = "{0} IS NULL".format(add_data_delimited)
        else:
            where_clause = "{0} IS NULL OR {0} = '' OR {0} = ' '".format(add_data_delimited)

        safe_print(u"\n===== 读取旧数据 =====")
        safe_print(u"查询条件：%s" % where_clause)

        # 读取字段：OBJECTID + 三个比对字段
        cursor_fields = [OBJECTID_FIELD] + CHECK_FIELDS
        safe_print(u"尝试读取的字段：%s" % ", ".join(cursor_fields))

        with arcpy.da.SearchCursor(fc_path, cursor_fields, where_clause) as cursor:
            count = 0
            for row in cursor:
                oid = row[0]
                field_values = []

                # 逐个处理检查字段
                for i in range(3):
                    field_name = CHECK_FIELDS[i]
                    field_obj = field_dict[field_name]
                    raw_value = row[i + 1]

                    # 安全获取字段值
                    str_val, status = get_field_value_safely(raw_value, field_obj.type)
                    field_values.append(str_val)

                    # 打印前5条数据的调试信息
                    if count < 5:
                        safe_print(u"旧数据OBJECTID=%d, %s字段：原始值=%s，状态=%s" %
                                   (oid, field_name, raw_value, status))

                combined_key = tuple(field_values)
                if combined_key not in combined_info:
                    combined_info[combined_key] = []
                combined_info[combined_key].append(oid)
                count += 1

            safe_print(u"\n成功读取%d条旧数据，获取%d种字段组合" % (count, len(combined_info)))
            return combined_info

    except Exception as e:
        safe_print(u"读取旧数据失败：%s" % str(e))
        return None


def update_duplicate_data(fc_path, combined_info, field_dict):
    """标记重复的新数据(ADD_DATA=3)和对应的旧数据(ADD_DATA=4)"""
    if not combined_info:
        safe_print(u"没有可比对的旧数据，无需标记")
        return 0, 0

    add_data_field = field_dict[ADD_DATA_FIELD]
    new_updated = 0
    old_updated = 0
    matched_oids = set()

    try:
        # 1. 标记重复的新数据
        add_data_delimited = arcpy.AddFieldDelimiters(fc_path, ADD_DATA_FIELD)
        if add_data_field.type in ['Integer', 'SmallInteger']:
            new_where = "{0} = 1".format(add_data_delimited)
        else:
            new_where = "{0} = '1'".format(add_data_delimited)

        safe_print(u"\n===== 处理新数据 =====")
        safe_print(u"查询条件：%s" % new_where)

        cursor_fields = [OBJECTID_FIELD] + CHECK_FIELDS + [ADD_DATA_FIELD]
        with arcpy.da.UpdateCursor(fc_path, cursor_fields, new_where) as cursor:
            for row in cursor:
                oid = row[0]
                field_values = []

                for i in range(3):
                    field_name = CHECK_FIELDS[i]
                    field_obj = field_dict[field_name]
                    raw_value = row[i + 1]

                    str_val, status = get_field_value_safely(raw_value, field_obj.type)
                    field_values.append(str_val)

                    # 打印前5条匹配数据的信息
                    if new_updated < 5 and tuple(field_values) in combined_info:
                        safe_print(u"新数据OBJECTID=%d, %s字段：值=%s，状态=%s" %
                                   (oid, field_name, raw_value, status))

                combined_key = tuple(field_values)
                if combined_key in combined_info:
                    # 更新新数据为3
                    if add_data_field.type in ['Integer', 'SmallInteger']:
                        row[-1] = 3
                    else:
                        row[-1] = "3"
                    cursor.updateRow(row)
                    new_updated += 1

                    # 记录匹配的旧数据OBJECTID
                    for old_oid in combined_info[combined_key]:
                        matched_oids.add(old_oid)

        # 2. 标记对应的旧数据
        if matched_oids:
            safe_print(u"\n===== 处理旧数据 =====")
            oid_list = list(matched_oids)
            old_where = "{0} IN ({1})".format(
                arcpy.AddFieldDelimiters(fc_path, OBJECTID_FIELD),
                ", ".join(map(str, oid_list))
            )
            safe_print(u"查询条件：%s" % old_where)

            with arcpy.da.UpdateCursor(fc_path, [OBJECTID_FIELD, ADD_DATA_FIELD], old_where) as cursor:
                for row in cursor:
                    if add_data_field.type in ['Integer', 'SmallInteger']:
                        row[1] = 4
                    else:
                        row[1] = "4"
                    cursor.updateRow(row)
                    old_updated += 1
                    if old_updated <= 5:
                        safe_print(u"旧数据OBJECTID=%d标记为重复(ADD_DATA=4)" % row[0])

    except Exception as e:
        safe_print(u"标记数据失败：%s" % str(e))
        return -1, -1

    return new_updated, old_updated


def main():
    safe_print(u"===== 开始重复数据双向标记 =====")

    # 要素类完整路径
    fc_path = os.path.join(gdb_path, feature_class)
    safe_print(u"处理的要素类：%s" % fc_path)

    # 验证要素类是否存在
    if not arcpy.Exists(fc_path):
        safe_print(u"错误：要素类'%s'不存在于数据库中" % fc_path)
        return False

    # 检查字段是否存在并获取详细信息
    field_dict = check_fields_exist(fc_path)
    if not field_dict:
        safe_print(u"字段检查未通过，无法继续处理")
        return False

    # 获取旧数据的字段组合及OBJECTID映射
    combined_info = get_old_data_combined_info(fc_path, field_dict)
    if combined_info is None:
        return False

    # 双向标记重复数据
    new_count, old_count = update_duplicate_data(fc_path, combined_info, field_dict)
    if new_count < 0 or old_count < 0:
        return False

    safe_print(u"\n===== 重复数据双向标记完成 =====")
    safe_print(u"新数据标记为重复(ADD_DATA=3)：%d条" % new_count)
    safe_print(u"旧数据标记为重复(ADD_DATA=4)：%d条" % old_count)
    return True


if __name__ == "__main__":
    if main():
        sys.exit(0)
    else:
        sys.exit(1)
